home *** CD-ROM | disk | FTP | other *** search
/ Tech Arsenal 1 / Tech Arsenal (Arsenal Computer).ISO / tek-04 / gs24src.zip / GXCOLOR.C < prev    next >
C/C++ Source or Header  |  1992-02-16  |  9KB  |  288 lines

  1. /* Copyright (C) 1989, 1990, 1991 Aladdin Enterprises.  All rights reserved.
  2.    Distributed by Free Software Foundation, Inc.
  3.  
  4. This file is part of Ghostscript.
  5.  
  6. Ghostscript is distributed in the hope that it will be useful, but
  7. WITHOUT ANY WARRANTY.  No author or distributor accepts responsibility
  8. to anyone for the consequences of using it or for whether it serves any
  9. particular purpose or works at all, unless he says so in writing.  Refer
  10. to the Ghostscript General Public License for full details.
  11.  
  12. Everyone is granted permission to copy, modify and redistribute
  13. Ghostscript, but only under the conditions described in the Ghostscript
  14. General Public License.  A copy of this license is supposed to have been
  15. given to you along with Ghostscript so you can know your rights and
  16. responsibilities.  It should be in a file named COPYING.  Among other
  17. things, the copyright notice and this notice must be preserved on all
  18. copies.  */
  19.  
  20. /* gxcolor.c */
  21. /* Private color procedures for Ghostscript library */
  22. #include "gx.h"
  23. #include "gserrors.h"
  24. #include "gxfixed.h"            /* for gxmatrix.h */
  25. #include "gxmatrix.h"
  26. #include "gxdevice.h"            /* for gx_color_index */
  27. #include "gzcolor.h"
  28. #include "gzht.h"
  29. #include "gzstate.h"
  30.  
  31. /* Imported procedures */
  32. void gx_color_render(P3(gs_color *, gx_device_color *, gs_state *));
  33.  
  34. /* Forward declarations */
  35. void gx_color_from_rgb(P1(gs_color *));
  36.  
  37. /* ------ Color setup routines ------ */
  38.  
  39. /* Set up black for writing into the character cache. */
  40. void
  41. gx_set_black(gs_state *pgs)
  42. {    register gs_color *pcolor = pgs->color;
  43.     pcolor->red = pcolor->green = pcolor->blue = pcolor->luminance = 0;
  44.     pcolor->luminance_set = 1;
  45.     pcolor->is_gray = 1;
  46.     pcolor->space = (byte)gs_color_space_DeviceGray;
  47.     gx_color_render(pcolor, pgs->dev_color, pgs);
  48. }
  49.  
  50. /* Set up a gray color.  This is an internal routine */
  51. /* for use by initialization and gx_remap_color. */
  52. void
  53. gx_set_gray_only(register gs_color *pcolor, color_param gray)
  54. {    pcolor->red = pcolor->green = pcolor->blue =
  55.       pcolor->luminance = gray;
  56.     pcolor->luminance_set = 1;
  57.     pcolor->is_gray = 1;
  58.     pcolor->space = (byte)gs_color_space_DeviceGray;
  59. }
  60.  
  61. /* Set up an RGB color.  This is an internal routine */
  62. /* for use by gx_remap_color. */
  63. void
  64. gx_set_rgb_only(register gs_color *pcolor,
  65.   color_param r, color_param g, color_param b)
  66. {    pcolor->red = r;
  67.     pcolor->green = g;
  68.     pcolor->blue = b;
  69.     gx_color_from_rgb(pcolor);
  70. }
  71.  
  72. /* Set up an RGB color. */
  73. void
  74. gx_color_from_rgb(register gs_color *pcolor)
  75. {    if ( pcolor->red == pcolor->green && pcolor->green == pcolor->blue )
  76.        {    pcolor->luminance = pcolor->red;    /* pick any one */
  77.         pcolor->is_gray = pcolor->luminance_set = 1;
  78.        }
  79.     else
  80.        {    /* Compute luminance later */
  81.         pcolor->is_gray = pcolor->luminance_set = 0;
  82.        }
  83.     pcolor->space = (byte)gs_color_space_DeviceRGB;
  84. }
  85.  
  86. /* Force a parameter into the range [0..1], */
  87. /* and convert to a color_param. */
  88. color_param
  89. gx_color_unit_param(floatp fval)
  90. {    if ( fval <= 0.0 )
  91.         return 0;
  92.     else if ( fval >= 1.0 )
  93.         return max_color_param;
  94.     else
  95.         return (color_param)(fval * max_color_param_float);
  96. }
  97.  
  98. /* Map a color_param through a transfer map. */
  99. color_param
  100. gx_color_param_map(color_param cv, color_param *values)
  101. {
  102. #define cp_frac_bits (color_param_bits - log2_transfer_map_size)
  103.     int cmi = cv >> cp_frac_bits;
  104.     color_param mv = values[cmi];
  105.     int rem, mdv;
  106.     /* Interpolate between two adjacent values if needed. */
  107.     rem = (cv & ((1 << cp_frac_bits) - 1)) - (cv >> (color_param_bits - cp_frac_bits));
  108.     if ( rem == 0 ) return mv;
  109.     else if ( rem > 0 ) mdv = values[cmi + 1] - mv;
  110.     else mdv = mv - values[cmi - 1];
  111. #if arch_ints_are_short
  112.     /* Only use long multiplication if necessary. */
  113.     if ( mdv > 1 << (16 - cp_frac_bits) )
  114.         return mv + (uint)(((ulong)rem * mdv) >> cp_frac_bits);
  115. #endif
  116.     return mv + ((rem * mdv) >> cp_frac_bits);
  117. #undef cp_frac_bits
  118. }
  119.  
  120. /* Remap the color in the graphics state. */
  121. void gx_render_color(P2(gs_color *, gs_state *));
  122. int
  123. gx_remap_color(gs_state *pgs)
  124. {    gs_color *pcolor = pgs->color;
  125.     gs_color mcolor;        /* color mapped by transfer procs */
  126. #define mapcp(p,c) gx_map_color_param(pgs, pcolor->c, p)
  127.     switch ( (gs_color_space)pcolor->space )
  128.        {
  129.     case gs_color_space_DeviceGray:
  130.         gx_set_gray_only(&mcolor, mapcp(gray, red));    /* any one */
  131.         break;
  132.     case gs_color_space_DeviceRGB:
  133.         gx_set_rgb_only(&mcolor, mapcp(red, red),
  134.                 mapcp(green, green), mapcp(blue, blue));
  135.         break;
  136.     default:
  137.         return_error(gs_error_undefined);
  138.        }
  139. #undef mapcp
  140.     gx_render_color(&mcolor, pgs);
  141.     return 0;
  142. }
  143. void
  144. gx_render_color(gs_color *pmcolor, gs_state *pgs)
  145. {    gx_color_render(pmcolor, pgs->dev_color, pgs);
  146. }
  147.  
  148. /* ------ Color conversion routines ------ */
  149.  
  150. /* Note: the color model conversion algorithms are taken from */
  151. /* Rogers, Procedural Elements for Computer Graphics, pp. 401-403. */
  152.  
  153. /* Compute (if necessary) and return the luminance of a color. */
  154. color_param
  155. gx_color_luminance(register gs_color *pcolor)
  156. {    if ( !pcolor->luminance_set )
  157.        {    pcolor->luminance =
  158.             (pcolor->red * (unsigned long)lum_red_weight +
  159.             pcolor->green * (unsigned long)lum_green_weight +
  160.             pcolor->blue * (unsigned long)lum_blue_weight +
  161.             (lum_all_weights / 2))
  162.             / lum_all_weights;
  163.         pcolor->luminance_set = 1;
  164.        }
  165.     return pcolor->luminance;
  166. }
  167.  
  168. /* Convert RGB to HSB */
  169. void
  170. gx_color_to_hsb(register gs_color *pcolor, color_param hsb[3])
  171. {
  172. #define rhue hsb[0]
  173. #define rsat hsb[1]
  174. #define rbri hsb[2]
  175.     if ( pcolor->is_gray )
  176.        {    rhue = 0;    /* arbitrary */
  177.         rsat = 0;
  178.         rbri = pcolor->red;    /* pick any one */
  179.        }
  180.     else
  181.        {    /* Convert rgb to hsb */
  182.         gs_color c;
  183.         color_param V, Temp;
  184.         long diff, H;
  185.         c.red = pcolor->red;
  186.         c.green = pcolor->green;
  187.         c.blue = pcolor->blue;
  188.         V = (c.red > c.green ? c.red : c.green);
  189.         if ( c.blue > V ) V = c.blue;
  190.         Temp = (c.red > c.green ? c.green : c.red);
  191.         if ( c.blue < Temp ) Temp = c.blue;
  192.         diff = V - Temp;
  193.         if ( V == c.red )
  194.             H = (c.green - c.blue) * max_color_param_long / diff;
  195.         else if ( V == c.green )
  196.             H = (c.blue - c.red) * max_color_param_long / diff + 2 * max_color_param_long;
  197.         else /* V == c.blue */
  198.             H = (c.red - c.green) * max_color_param_long / diff + 4 * max_color_param_long;
  199.         if ( H < 0 ) H += 6 * max_color_param_long;
  200.         rhue = H / 6;
  201.         rsat = diff * max_color_param_long / V;
  202.         rbri = V;
  203.        }
  204. #undef rhue
  205. #undef rsat
  206. #undef rbri
  207. }
  208.  
  209. /* Complete color specified by hsb */
  210. void
  211. gx_color_from_hsb(register gs_color *pcolor,
  212.   color_param hue, color_param saturation, color_param brightness)
  213. {    if ( saturation == 0 )
  214.        {    pcolor->red = pcolor->green = pcolor->blue = brightness;
  215.        }
  216.     else
  217.        {    /* Convert hsb to rgb. */
  218.         /* We rely on the fact that the product of two */
  219.         /* color_params fits into an unsigned long. */
  220.         ulong V = brightness;    /* force arithmetic to long */
  221.         color_param S = saturation;
  222. #define mcp max_color_param
  223. #define mcpl max_color_param_long
  224. #define mcp6 (mcp / 6 + 1)
  225.         ulong F = (hue % mcp6) * 6;    /* ditto */
  226.         int I = hue / mcp6;
  227.         color_param M = V * (mcpl - S) / mcpl;
  228.         color_param N = V * (mcpl - S * F / mcpl) / mcpl;
  229.         color_param K = V * (mcpl - S * (mcpl - F) / mcpl) / mcpl;
  230. #undef mcp6
  231. #undef mcpl
  232. #undef mcp
  233.         color_param R, G, B;
  234.         switch ( I )
  235.            {
  236.         default: R = V; G = K; B = M; break;
  237.         case 1: R = N; G = V; B = M; break;
  238.         case 2: R = M; G = V; B = K; break;
  239.         case 3: R = M; G = N; B = V; break;
  240.         case 4: R = K; G = M; B = V; break;
  241.         case 5: R = V; G = M; B = N; break;
  242.            }
  243.         pcolor->red = R;
  244.         pcolor->green = G;
  245.         pcolor->blue = B;
  246.        }
  247.     gx_color_from_rgb(pcolor);    /* compute luminance */
  248. }
  249.  
  250. /* ------ Internal routines ------ */
  251.  
  252. /* Heapsort (algorithm 5.2.3H, Knuth vol. 2, p. 146), */
  253. /* modified for 0-origin indexing. */
  254. void
  255. gx_sort_ht_order(ht_bit *recs, uint N)
  256. {    uint l = N >> 1;
  257.     uint r = N - 1;
  258.     uint j;
  259.     ht_bit R;
  260.     if ( N <= 1 ) return;
  261. #define key(m) recs[m].mask
  262. #define K R.mask
  263.     while ( 1 )
  264.        {    if ( l > 0 )
  265.             R = recs[--l];
  266.         else
  267.            {    R = recs[r];
  268.             recs[r] = recs[0];
  269.             if ( --r == 0 )
  270.                {    recs[0] = R;
  271.                 break;
  272.                }
  273.            }
  274.         j = l;
  275.         while ( 1 )
  276.            {    uint i = j;
  277.             j = j + j + 1;
  278.             if ( j < r )
  279.                 if ( key(j) < key(j + 1) ) j++;
  280.             if ( j > r || K >= key(j) )
  281.                {    recs[i] = R;
  282.                 break;    /* to outer loop */
  283.                }
  284.             recs[i] = recs[j];
  285.            }
  286.        }
  287. }
  288.